package com.platform.core.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.platform.comm.service.impl.CommonBizImpl;
import com.platform.core.repository.SysMsgRecordRepository;
import com.platform.core.repository.SysUserRepository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.Tuple;
import com.platform.comm.dto.DtoMapper;
import com.platform.comm.entity.CommDataInfoEntity;
import com.platform.comm.enums.YnEnum;
import com.platform.comm.exceptions.RestApiException;
import com.platform.comm.jwt.TokenInfoUtil;
import com.platform.comm.util.DateTimeUtil;
import com.platform.core.entity.QSysMsgManageEntity;
import com.platform.core.entity.QSysMsgRecordEntity;
import com.platform.core.entity.QSysUser;
import com.platform.core.entity.SysMsgManageEntity;
import com.platform.core.entity.SysMsgRecordEntity;
import com.platform.core.entity.SysUser;
import com.platform.core.service.SysMsgRecordBiz;
import com.platform.core.service.SysUserService;
import com.platform.dto.SysMsgManageVo;
import com.platform.dto.SysMsgRecordVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * Description: LcodeMsgRecord-业务接口实现类
 *
 * @author Coder
 */
@Slf4j
@Service
public class SysMsgRecordBizImpl extends CommonBizImpl<SysMsgRecordRepository, SysMsgRecordEntity, String> implements SysMsgRecordBiz {

    private final QSysMsgRecordEntity qSysMsgRecordEntity = QSysMsgRecordEntity.sysMsgRecordEntity;
    private final QSysMsgManageEntity qSysMsgManageEntity = QSysMsgManageEntity.sysMsgManageEntity;
    private final QSysUser qSysUser = QSysUser.sysUser;
    private final DtoMapper mapper;
    private final TokenInfoUtil infoUtil;
    private final SysUserRepository userRepository;
    private final SysUserService userService;
    private final CommDataInfoBizImpl dataInfoBiz;


    public SysMsgRecordBizImpl(SysMsgRecordRepository lcodeMsgRecordRepository, DtoMapper mapper, TokenInfoUtil infoUtil,
                               SysUserRepository userRepository, SysUserService userService,CommDataInfoBizImpl dataInfoBiz) {
        super(lcodeMsgRecordRepository);
        this.mapper = mapper;
        this.infoUtil = infoUtil;
        this.userRepository = userRepository;
        this.userService = userService;
        this.dataInfoBiz = dataInfoBiz;
    }

    @Override
    public List<SysMsgRecordEntity> insertRecord(List<SysMsgRecordVo> msgRecordVoList) {
        if (CollUtil.isEmpty(msgRecordVoList)) {
            return new ArrayList<>();
        }
        return this.repository.saveAll(msgRecordVoList.stream().map(x -> mapper.map(x, SysMsgRecordEntity.class)).collect(Collectors.toList()));
    }

    @Override
    public Page<Map<String, Object>> search(Map<String, String> map, Pageable of) {
        String msgTitle = map.getOrDefault("msgTitle", "");
        String sendName = map.getOrDefault("sendName", "");
        String readStatus = map.getOrDefault("readStatus", "");
        String msgType = map.getOrDefault("msgType", "");
        String expireStatus = map.getOrDefault("expireStatus", "");
        String beginDate = map.getOrDefault("beginDate", "");
        String endDate = map.getOrDefault("endDate", "");
        String notifyType = map.getOrDefault("notifyType", "");

        String userId = infoUtil.getUserId();

        BooleanBuilder builder = new BooleanBuilder();
        builder.and(qSysMsgRecordEntity.recevieUser.eq(userId));
        builder.and(qSysMsgRecordEntity.flag.eq(YnEnum.Y.key()));
        if (StringUtils.isNotEmpty(msgTitle)) {
            builder.and(qSysMsgManageEntity.msgTitle.contains(msgTitle));
        }
        //发件人
        if (StringUtils.isNotEmpty(sendName)) {
            builder.and(qSysUser.realName.contains(sendName).and(qSysUser.delFlag.eq(YnEnum.N)));
        }
        if (StringUtils.isNotEmpty(readStatus)) {
            builder.and(qSysMsgRecordEntity.readStatus.eq(readStatus));
        }
        if (StringUtils.isNotEmpty(msgType)) {
            builder.and(qSysMsgManageEntity.msgType.eq(msgType));
        }
        if (StringUtils.isNotEmpty(expireStatus)) {
            builder.and(qSysMsgManageEntity.expireStatus.eq(expireStatus));
        }
        if (StringUtils.isNotEmpty(beginDate)) {
            LocalDateTime newBegin = DateTimeUtil.parseStdLongTimeStr(beginDate+" 00:00:00");
            LocalDateTime newEnd = DateTimeUtil.parseStdLongTimeStr(endDate+" 23:59:59");
            builder.and(qSysMsgManageEntity.createDate.between(newBegin, newEnd));
        }
        if (StringUtils.isNotEmpty(notifyType)) {
            builder.and(qSysMsgManageEntity.notifyType.eq(notifyType));
        }

        return userRepository.findAll(builder, of, jpqlQuery -> jpqlQuery
                        .leftJoin(qSysMsgManageEntity).on(qSysMsgManageEntity.createBy.eq(qSysUser.id))
                        .leftJoin(qSysMsgRecordEntity).on(qSysMsgRecordEntity.msgId.eq(qSysMsgManageEntity.id)).orderBy(qSysMsgManageEntity.createDate.desc())
                , qSysUser.realName, qSysMsgManageEntity, qSysMsgRecordEntity
        ).map(x -> {
            SysMsgManageEntity sysMsgManageEntity = x.get(qSysMsgManageEntity);
            SysMsgRecordEntity msgRecordEntity = x.get(qSysMsgRecordEntity);
            Map<String, Object> result = Maps.newHashMap();
            result.put("id", msgRecordEntity.getId());
            result.put("msgTitle", sysMsgManageEntity.getMsgTitle());
            result.put("msgContent", sysMsgManageEntity.getMsgContent());
            result.put("msgType", sysMsgManageEntity.getMsgType());
            result.put("createName", x.get(qSysUser.realName));
            result.put("createDate", DateTimeUtil.toStdLongTimeStr(sysMsgManageEntity.getCreateDate()));
            result.put("readStatus", msgRecordEntity.getReadStatus());
            result.put("expireStatus", sysMsgManageEntity.getExpireStatus());
            return result;
        });
    }


    @Override
    public SysMsgRecordVo detail(Map<String, String> map) {
        String id = map.getOrDefault("id", "");
        Preconditions.checkArgument(StringUtils.isNotEmpty(id), "id不能为空");
        Optional<Tuple> one = this.repository.findOne(qSysMsgRecordEntity.id.eq(id),
                jpqlQuery -> jpqlQuery.leftJoin(qSysMsgManageEntity).on(qSysMsgManageEntity.id.eq(qSysMsgRecordEntity.msgId))
                , qSysMsgRecordEntity, qSysMsgManageEntity);
        if (!one.isPresent()) {
            throw new RestApiException("未查到该记录");
        }
        Tuple tuple = one.get();
        SysMsgRecordEntity msgRecordEntity = tuple.get(qSysMsgRecordEntity);
        SysMsgRecordVo recordVo = mapper.map(msgRecordEntity, SysMsgRecordVo.class);
        SysMsgManageEntity msgManageEntity = tuple.get(qSysMsgManageEntity);
        SysMsgManageVo manageVo = mapper.map(msgManageEntity, SysMsgManageVo.class);
        SysUser sysUser = userService.fetchById(manageVo.getCreateBy());
        manageVo.setCreateName(sysUser.getRealName());
        manageVo.setFileList(getFileId(manageVo.getFileId()));
        recordVo.setMsgManageVo(manageVo);
        assert msgRecordEntity != null;
        if (msgRecordEntity.getReadStatus().equals(YnEnum.N.key())) {
            msgRecordEntity.setReadStatus(YnEnum.Y.key());
            msgRecordEntity.setReadTime(LocalDateTime.now());
            saveEntity(msgRecordEntity);
        }
        return recordVo;
    }


    @Override
    public void modifyReadStatus() {
        String userId = infoUtil.getUserId();
        List<SysMsgRecordEntity> sysMsgRecordEntities = queryAll(qSysMsgRecordEntity.flag.eq(YnEnum.Y.key()).and(qSysMsgRecordEntity.recevieUser.eq(userId)))
                .stream().peek(x-> {
                    x.setReadStatus(YnEnum.Y.key());
                    x.setReadTime(LocalDateTime.now());
                }).collect(Collectors.toList());
        this.repository.saveAll(sysMsgRecordEntities);
    }


    @Override
    public void deleteById(Map<String, String> map) {
        String id = map.getOrDefault("id", "");
        Preconditions.checkArgument(StringUtils.isNotEmpty(id), "id不能为空");
        SysMsgRecordEntity msgRecordEntity = fetchById(id);
        msgRecordEntity.setFlag(YnEnum.N.key());
        saveEntity(msgRecordEntity);
    }

    @Override
    public List<SysMsgRecordVo> searchByMsgId(String msgId) {
        return this.repository.findAll(qSysMsgRecordEntity.msgId.eq(msgId), jpqlQuery ->
                        jpqlQuery.leftJoin(qSysUser).on(qSysUser.id.eq(qSysMsgRecordEntity.recevieUser))
                , qSysUser.realName, qSysMsgRecordEntity)
                .stream().map(x -> {
            SysMsgRecordVo map = mapper.map(x.get(qSysMsgRecordEntity), SysMsgRecordVo.class);
            map.setRecevieName(x.get(qSysUser.realName));
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    public Page<SysMsgRecordVo> searchRecord(Map<String, String> map,Pageable of) {
        String msgId = map.getOrDefault("msgId", "");
        String recevieName = map.getOrDefault("recevieName", "");
        Preconditions.checkArgument(StringUtils.isNotEmpty(msgId), "msgId不能为空");
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(qSysMsgRecordEntity.msgId.eq(msgId));
        if (StringUtils.isNotEmpty(recevieName)) {
            builder.and(qSysUser.realName.contains(recevieName));
        }
        return this.repository.findAll(builder, of,
                jpqlQuery -> jpqlQuery.leftJoin(qSysUser).on(qSysUser.id.eq(qSysMsgRecordEntity.recevieUser))
                , qSysUser.realName, qSysMsgRecordEntity)
                .map(x -> {
                    SysMsgRecordVo recordVo = mapper.map(x.get(qSysMsgRecordEntity), SysMsgRecordVo.class);
                    recordVo.setRecevieName(x.get(qSysUser.realName));
                    return recordVo;
                });
    }


    @Override
    public List<Map<String, String>> getFileId(String fileId) {
        if (StringUtils.isNotEmpty(fileId)) {
            List<Map<String, String>> fileList = com.google.common.collect.Lists.newArrayList();
            for (String file : fileId.split(",")) {
                CommDataInfoEntity commDataInfoEntity = dataInfoBiz.queryCommDataImpById(file);
                if (Objects.nonNull(commDataInfoEntity)) {
                    Map<String, String> fileMap = Maps.newHashMap();
                    fileMap.put("fileName", commDataInfoEntity.getFileName());
                    fileMap.put("id", file);
                    fileList.add(fileMap);
                }
            }
            return fileList;
        }
        return null;
    }


    @Override
    public void editReadStatus(String id) {
        SysMsgRecordEntity msgRecordEntity = fetchById(id);
        msgRecordEntity.setReadStatus(YnEnum.Y.key());
        msgRecordEntity.setReadTime(LocalDateTime.now());
        saveEntity(msgRecordEntity);
    }
}
